; int cargar_arbol_huffman(codigo_t *tabla_codigo, nodo_arbol_t **a);

%include "macros/nodo_arbol_t.mac"
%include "macros/personalizada.mac"
%include "macros/codigo_t.mac"

extern calloc

global cargar_arbol_huffman

%define ptr_tabla_codigo [ebp + 8]
%define ptr_ptr_nodo_arbol [ebp + 12]

section .text

cargar_arbol_huffman:
	push ebp
	mov ebp, esp
	push esi
	push edi
	push ebx
	
	; Reservamos memoria para el nodo padre del arbol.
	push dword 21
	push dword 1
	call calloc
	add esp, 8
	cmp eax, 0
	je NEAR error
	
	mov edi, ptr_ptr_nodo_arbol
	mov [edi], eax ; Guardamos el puntero del arbol que vamos a crear.
	mov edi, eax ; edi = puntero al nodo padre del arbol.
	
	mov ecx, 256 ; ecx = cantidad de elementos en la tabla de codigos.
	
ciclo:
	push ecx
	
	mov esi, ptr_tabla_codigo ; esi = puntero a la tabla de codigos.
	shl ecx, 4 ; Multiplico ecx por 16.
	sub ecx, 16 ; Resto a ecx 16.
	mov ebx, [esi + ecx + off_valido_cod] ; ebx = validez del codigo actual.
	cmp ebx, invalido
	je NEAR codigo_invalido
	
	mov ebx, [esi + ecx + off_codigo_rev_cod] ; ebx = codigo reverso actual.
	mov ecx, [esi + ecx + off_long_codigo_cod] ; ecx = longitud del codigo reverso actual.
	
	xor esi, esi ; esi = puntero al padre.
	
ciclo2:
	push ecx
	
	rcr ebx, 1 ; Nos movemos en el árbol según el bit menos significativo del código reverso (lo pasamos al carry y miramos si es 0 o 1).
	jnc rama_der
	
rama_izq:
	cmp dword [edi + off_ptr_izq_na], 0 ; Nos fijamos si ya hay un nodo en la rama izquierda.
	je no_tengo_nodo_izq
	
tengo_nodo_izq:
	mov esi, edi
	mov edi, [edi + off_ptr_izq_na]
	jmp sigo
	
no_tengo_nodo_izq:
	; Reservo memoria para el nuevo nodo arbol.
	push dword 21
	push dword 1
	call calloc
	add esp, 8
	cmp eax, 0
	je NEAR error
	
	mov [edi + off_ptr_izq_na], eax
	mov [edi + off_ptr_padre_na], esi
	mov esi, edi
	mov edi, eax
	jmp sigo
	
rama_der:
	cmp dword [edi + off_ptr_der_na], 0 ; Nos fijamos si ya hay un nodo en la rama derecha.
	je no_tengo_nodo_der
	
tengo_nodo_der:
	mov esi, edi
	mov edi, [edi + off_ptr_der_na]
	jmp sigo
	
no_tengo_nodo_der:
	; Reservo memoria para el nuevo nodo arbol.
	push dword 21
	push dword 1
	call calloc
	add esp, 8
	cmp eax, 0
	je error
	
	mov [edi + off_ptr_der_na], eax
	mov [edi + off_ptr_padre_na], esi
	mov esi, edi
	mov edi, eax

sigo:
	pop ecx
	
	dec ecx
	cmp ecx, 0
	jne NEAR ciclo2
	
	pop ecx
	dec ecx
	mov [edi + off_simbolo_na], ecx
	inc ecx
	mov dword [edi + off_valido_na], valido
	mov [edi + off_ptr_padre_na], esi
	
	mov edi, ptr_ptr_nodo_arbol ; edi = ptr ptr nodo arbol de entrada.
	mov edi, [edi] ; edi = ptr nodo arbol.
	
	dec ecx
	cmp ecx, 0
	jne NEAR ciclo
	
	xor eax, eax
	jmp fin
	
codigo_invalido:
	pop ecx
	
	dec ecx
	cmp ecx, 0
	jne NEAR ciclo
	
	xor eax, eax
	jmp fin
	
error:
	mov eax, error_code
	
fin:
	pop ebx
	pop edi
	pop esi
	pop ebp
	ret
